package com.monkeyk.sos.service.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.monkeyk.sos.domain.dto.ApplicationDetailsDto;
import com.monkeyk.sos.domain.model.ApplicationDetails;
import com.monkeyk.sos.domain.oauth.OauthClientDetails;
import com.monkeyk.sos.domain.oauth.OauthRepository;
import com.monkeyk.sos.domain.shared.GuidGenerator;
import com.monkeyk.sos.service.ApplicationService;
import com.monkeyk.sos.service.OauthService;

@Service("applicationService")
public class ApplicationServiceImpl implements ApplicationService {

	@Autowired
	private OauthRepository	oauthRepository;
	
	@Autowired
    private OauthService  oauthService;

	@Autowired
	private JdbcTemplate	jdbcTemplate;

	/*
	 * 保存应用基本信息和客户端信息
	 */
	@Override
	@Transactional
	public String registerApplicationDetails(ApplicationDetailsDto formDto, int cooperId) {
		ApplicationDetailsDto appDetails = getApplicationDetailsDto(formDto);
		oauthRepository.saveOauthClientDetails(appDetails.createDomain());
		Long appId = saveApplicationDetails(appDetails.createApplicationDetails());
		saveApplicationClient(appId, appDetails.createDomain().clientId());
		saveCooperApp(cooperId, appId);
		return appId.toString();
	}
	
	/*
	 * 保存应用基本信息
	 */
	private Long saveApplicationDetails(final ApplicationDetails applicationDetails) {
		final String sql = " insert into application_details(app_name,app_platform,app_profile,app_describe,web_name,web_domains,t_createdate) values (?,?,?,?,?,?,?)";
		KeyHolder keyHolder = new GeneratedKeyHolder();
		this.jdbcTemplate.update(new PreparedStatementCreator() {
			public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
				PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
				ps.setString(1, applicationDetails.getAppName());
				ps.setString(2, applicationDetails.getAppPlatform());
				ps.setString(3, applicationDetails.getAppProfile());
				ps.setString(4, applicationDetails.getAppDescribe());
				ps.setString(5, applicationDetails.getWebName());
				ps.setString(6, applicationDetails.getWebDomains());
				ps.setDate(7, (java.sql.Date) new Date());
				return ps;
			}
		}, keyHolder);
		Long generatedId = keyHolder.getKey().longValue();
		return generatedId;

	}

	/*
	 * 应用-客户端信息表 app_client
	 */
	private void saveApplicationClient(final Long appId, final String clientId) {
		final String sql = " insert into app_client(app_id,client_id) values (?,?)";
		this.jdbcTemplate.update(sql, new PreparedStatementSetter() {
			@Override
			public void setValues(PreparedStatement ps) throws SQLException {
				ps.setLong(1, appId);
				ps.setString(2, clientId);
			}
		});
	}
	
	/*
	 * 合作者-应用信息表 cooper_app
	 */
	private void saveCooperApp(final int cooperId, final Long appId) {
		final String sql = " insert into cooper_app(cooper_id,app_id) values (?,?)";
		this.jdbcTemplate.update(sql, new PreparedStatementSetter() {
			@Override
			public void setValues(PreparedStatement ps) throws SQLException {
				ps.setInt(1, cooperId);
				ps.setLong(2, appId);
			}
		});
	}

	/*
	 * 获得应用详情
	 */
	@Override
	public ApplicationDetailsDto getApplicationDetailsDto(String appId) {
		Map<String, Object> map = getClientId(appId);
		OauthClientDetails clientDetails = oauthRepository.findOauthClientDetails(map.get("clientId").toString());
		return new ApplicationDetailsDto(clientDetails, (ApplicationDetails) map.get("appDetails"));
	}

	/*
	 * 获得应用详情和clientId
	 */
	private Map<String, Object> getClientId(String appId) {
		Map<String, Object> map = new HashMap<String, Object>();
		String sqlApp = " select * from application_details where  id = ?";
		java.util.List<ApplicationDetails> appDetailsList = this.jdbcTemplate.query(sqlApp, new Object[] { appId },
				new RowMapper<ApplicationDetails>() {
					@Override
					public ApplicationDetails mapRow(ResultSet rs, int rowNum) throws SQLException {
						ApplicationDetails appDetails = new ApplicationDetails();
						appDetails.setAppId(rs.getLong("id"));
						appDetails.setAppName(rs.getString("app_name"));
						appDetails.setAppPlatform(rs.getString("app_platform"));
						appDetails.setAppProfile(rs.getString("app_profile"));
						appDetails.setAppDescribe(rs.getString("app_describe"));
						appDetails.setWebName(rs.getString("web_name"));
						appDetails.setWebDomains(rs.getString("web_domains"));
						appDetails.setWebRecord(rs.getString("web_record"));
						appDetails.setStatus(rs.getInt("status"));
						return appDetails;
					}
				});
		final String sqlClientId = " select client_id from app_client where  app_id = '" + appId + "'";
		String clientId = this.jdbcTemplate.queryForObject(sqlClientId, String.class);
		map.put("clientId", clientId);
		map.put("appDetails", appDetailsList.get(0));
		return map;
	}

	@Transactional
	@Override
	public void updateApplicationDetails(ApplicationDetailsDto formDto, String appId) {
		ApplicationDetails appDetails = formDto.createApplicationDetails();
		int status = appDetails.getStatus() == 2 ? 2:1;
		updateAppDetails(appDetails, appId,status);
	}

	/*
	 * 更新应用基本信息
	 */
	private void updateAppDetails(final ApplicationDetails appDetails, final String appId,final int status) {
		String sqlApp = " update application_details set app_name = ?,app_platform = ? ,app_profile = ? ,app_describe = ? ,web_name = ? ,web_domains = ? ,web_record = ?,status=? ,t_updatedate=? where id = ?";
		this.jdbcTemplate.update(sqlApp, new PreparedStatementSetter() {
			@Override
			public void setValues(PreparedStatement ps) throws SQLException {
				ps.setObject(1, appDetails.getAppName());
				ps.setObject(2, appDetails.getAppPlatform());
				ps.setObject(3, appDetails.getAppProfile());
				ps.setObject(4, appDetails.getAppDescribe());
				ps.setObject(5, appDetails.getWebName());
				ps.setObject(6, appDetails.getWebDomains());
				ps.setObject(7, appDetails.getWebRecord());
				ps.setObject(8, status);
				ps.setObject(9, new Date());
				ps.setObject(10, appId);
			}
		});

	}

	@SuppressWarnings("unused")
	private void updateClientDetails(final OauthClientDetails clientDetails) {
		String sqlApp = " update oauth_client_details set clientSecret = ? where client_id = ?";
		this.jdbcTemplate.update(sqlApp, new PreparedStatementSetter() {
			@Override
			public void setValues(PreparedStatement ps) throws SQLException {
				ps.setObject(1, clientDetails.clientSecret());
				ps.setObject(2, clientDetails.clientId());
			}
		});

	}
	
	
	/*
	 * 组装ApplicationDetailsDto
	 */
	private ApplicationDetailsDto getApplicationDetailsDto(ApplicationDetailsDto appDetails) {
		Map<String,String> map = oauthService.createClientIdAndSecret();
		appDetails.setClientId(map.get("clientId"));
		appDetails.setClientSecret(map.get("clientSecret"));
		return appDetails;
	}
	
	@Transactional
	@Override
	public void updateAdvancedAppDetail(ApplicationDetailsDto formDto,final String clientId) {
		updateAdvancedAppDetail(formDto.createDomain(),clientId);
	}

	/**
	 * 更新应用高级信息
	 */
	private void updateAdvancedAppDetail(final OauthClientDetails oauth,final String clientId) {
		String sqlApp = " update oauth_client_details set resource_ids = ?,scope = ? ,authorized_grant_types = ? ,web_server_redirect_uri = ?  where client_id = ?";
		this.jdbcTemplate.update(sqlApp, new PreparedStatementSetter() {
			@Override
			public void setValues(PreparedStatement ps) throws SQLException {
				ps.setObject(1, oauth.resourceIds());
				ps.setObject(2, oauth.scope());
				ps.setObject(3, oauth.authorizedGrantTypes());
				ps.setObject(4, oauth.webServerRedirectUri());
				ps.setObject(5, clientId);
			}
		});
	}

	@Override
	public String resetClientSecret(String clientId) {
		String clientSecret = GuidGenerator.generate();
		this.jdbcTemplate.update("update oauth_client_details set client_secret = '"+clientSecret+"'  where client_id = '"+clientId+"'");
		return clientSecret;
	}
	/*
	 * 查询WEB应用名是否存在
	 */
	@Override
	public boolean checkWebName(String webName) {
		final String sql = " select count(0) from application_details where  web_name = '"+webName+"'";
		Integer coun = this.jdbcTemplate.queryForObject(sql,Integer.class);
		if(coun == 0){
			return true;
		}else{
			return false;
		}
	}
	/*
	 * 更新应用状态
	 */
	@Override
	public void updateAppStatus(String appId, int status) {
		this.jdbcTemplate.update("update application_details set status ='"+status+"' where id="+appId);
	}
	/*
	 * 删除应用
	 */
	@Transactional
	@Override
	public boolean deletApp(String appId) {
		try {
			this.jdbcTemplate.update("delete  a.*,b.*,c.*,d.* from  cooper_app d left join application_details a on d.app_id = a.id left join app_client b on a.id= b.app_id left join oauth_client_details c on b.client_id = c.client_id where d.app_id="+appId);
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	
	
}
